package cn.pugle.base.net.socket;

import cn.pugle.base.net.socket.client.CONS;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 采用传统IO方式编写的Socket服务器
 * 理解socket工作方式
 * serverSocket的accept方法会阻塞直到发生一个连接，方法返回一个socket
 *
 * todo 测试服务器和客户的主动和被动关闭连接的情况
 *
 * @author tzp
 * @date 15-12-7
 */
public class SocketStreamServer {
    static ExecutorService threadPool;

    static {
            threadPool = Executors.newFixedThreadPool(10);
    }

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(CONS.SERVER_PORT, 100, CONS.inetAddress);
            Socket incomeSocket;
            System.out.println("begin to accept connection");
            while (!Thread.interrupted()) {
                incomeSocket = serverSocket.accept();
                threadPool.execute(new MySocketWorker(incomeSocket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class MySocketWorker implements Runnable {
        Socket socketToTreat;

        public MySocketWorker(Socket socketToTreat) {
            this.socketToTreat = socketToTreat;
        }

        @Override
        public void run() {
            try {
                System.out.println("connection comming in");
                InputStream in = socketToTreat.getInputStream();
                OutputStream out = socketToTreat.getOutputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                String strIn = null;
                //一个从socket来的Stream，是不能知道自己是何时结束的，判断的方式是由上层协议来实现的，如HTTP的空行。这里用TAIL字符串
                //client是每隔10
                while ((strIn = br.readLine()) != null && strIn.lastIndexOf(CONS.PROTOCOL_TAIL) == -1) {
                    System.out.println("begin treat socket, remoteAddress: " + socketToTreat.getRemoteSocketAddress() + " port: " + socketToTreat.getPort());
                    System.out.println("It says: " + strIn);
                    out.write(("Server Receive " + strIn + "\n").getBytes(CONS.CHARSET_NAME));
                }
                System.out.println("connection finish");
                socketToTreat.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}
